package com.softserveinc.ita.kaiji.web.controller;

import java.util.Set;

import com.softserveinc.ita.kaiji.model.game.Game;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import com.softserveinc.ita.kaiji.model.Card;
import com.softserveinc.ita.kaiji.model.game.GameHistory;
import com.softserveinc.ita.kaiji.model.game.GameInfo;
import com.softserveinc.ita.kaiji.model.player.Player;
import com.softserveinc.ita.kaiji.service.GameService;
import com.softserveinc.ita.kaiji.service.GameServiceImpl;

import javax.servlet.AsyncContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author Eugene Semenkov
 * @version 1.1.2
 * @since 17.03.14
 */

@Controller
@RequestMapping("/game")
@SessionAttributes({"personId","enemyObject"})

public class PlayGameController {

    private final long TURN_TIMEOUT = 60000L;
	private static Logger logger = Logger
			.getLogger(PlayGameController.class);

    @Autowired
	private GameService gameService;

	@RequestMapping(value = "/{gameId}/",
			method = { RequestMethod.GET, RequestMethod.POST })
	public String initGame(@PathVariable Integer gameId,
			Model model) {

        Integer personId = (Integer)model.asMap().get("personId");
		if (logger.isTraceEnabled())
			logger.trace("Starting initGame.");

		logger.info("GameId: " + gameId + ". PersonId: " + personId);

		GameHistory gameHistory = gameService.getGameHistory(gameId);
		GameInfo gameInfo = gameHistory.getGameInfo();
		Set<Player> players = gameInfo.getPlayers();
		
		Player person = null;
		Player enemy = null;

		for (Player player : players) {
			if (player.getId().equals(personId)) {
				person = player;
			} else {
				enemy = player;
			}
		}

		model.addAttribute("gameId", gameId);
		model.addAttribute("gameHistory", gameHistory);
		model.addAttribute("playerObject", person);
		model.addAttribute("enemyObject", enemy);


		return "play-game";

	}

	@RequestMapping(value = "/{gameId}/card/{cardName}/",
			method = RequestMethod.GET)
	public String getCard(@PathVariable Integer gameId,
			@PathVariable String cardName,
			Model model,  HttpServletRequest request, HttpServletResponse response) {



        Integer personId = (Integer)model.asMap().get("personId");
		if (logger.isTraceEnabled())
			logger.trace("Starting getCard.");
		
		logger.info("GameId: " + gameId + ". CardId: "
				+ cardName + ". PersonId: " + personId);

		Card playerChosenCard = null;
		for (Card card : Card.values()) {
			if (card.name().equals(cardName)) {
				playerChosenCard = card;
			}
		}

		gameService.makeTurn(gameId, personId, playerChosenCard);
        Player player = gameService.getPlayerById(personId);
        Player enemy = (Player)model.asMap().get("enemyObject");

        //starting async
        if (!enemy.isBot() & (enemy.getCardCount()!= player.getCardCount())) {
            final AsyncContext asyncContext = request.startAsync(request, response);
            asyncContext.setTimeout(TURN_TIMEOUT);
        asyncContext.start(new playerTurnCheker(asyncContext, gameId, gameService, enemy.getId(), personId));
        }
		return "redirect:/game/" + gameId + "/";

	}

    @RequestMapping(value = "join")
    public String getJoinForm() {
        return "join-game";
    }

}

class playerTurnCheker implements Runnable {


    private GameService gameService;
    AsyncContext asyncContext;
    Player enemy;
    Player player;
   Integer gameId;

    public playerTurnCheker(AsyncContext asyncContext,
                            Integer gameId,
                            GameService gameService,
                            Integer enemyId,
                            Integer personId) {
        this.asyncContext = asyncContext;
        this.gameId = gameId;
        this.gameService = gameService;
        enemy = gameService.getPlayerById(enemyId);
        player = gameService.getPlayerById(personId);
    }

    @Override
    public void run() {
        if (!enemy.isBot()) {
        try {

            while(enemy.getCardCount()!= player.getCardCount()){
                Thread.sleep(4000);
                enemy = gameService.getPlayerById(enemy.getId());
                player = gameService.getPlayerById(player.getId());
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        }
        asyncContext.complete();
    }
}

